#include <string.h>
#include <desc.h>
#include <vsprintf.h>
#include <panic.h>
#include <cpu.h>
#include <page.h>
#include <isr.h>
#include <page.h>
#include <debug.h>

/* sekiOS
 *
 * isr.c - ISR's and other fun stuff
 *
 * HERE THERE BE DRAGONS - don't mess with stuff!
 *
 */

/* This is a very repetitive function... it's not hard, it's
*  just annoying. As you can see, we set the first 32 entries
*  in the IDT to the first 32 ISRs. We can't use a for loop
*  for this, because there is no way to get the function names
*  that correspond to that given entry. We set the access
*  flags to 0x8E. This means that the entry is present, is
*  running in ring 0 (kernel level), and has the lower 5 bits
*  set to the required '14', which is represented by 'E' in
*  hex. */
void
isrs_install ()
{
  idt_set_gate (0, (unsigned int)isr0, 0x08, 0x8E);
  idt_set_gate (1, (unsigned int)isr1, 0x08, 0x8E);
  idt_set_gate (2, (unsigned int)isr2, 0x08, 0x8E);
  idt_set_gate (3, (unsigned int)isr3, 0x08, 0x8E);
  idt_set_gate (4, (unsigned int)isr4, 0x08, 0x8E);
  idt_set_gate (5, (unsigned int)isr5, 0x08, 0x8E);
  idt_set_gate (6, (unsigned int)isr6, 0x08, 0x8E);
  idt_set_gate (7, (unsigned int)isr7, 0x08, 0x8E);
  idt_set_gate (8, (unsigned int)isr8, 0x08, 0x8E);
  idt_set_gate (9, (unsigned int)isr9, 0x08, 0x8E);
  idt_set_gate (10, (unsigned int)isr10, 0x08, 0x8E);
  idt_set_gate (11, (unsigned int)isr11, 0x08, 0x8E);
  idt_set_gate (12, (unsigned int)isr12, 0x08, 0x8E);
  idt_set_gate (13, (unsigned int)isr13, 0x08, 0x8E);
  idt_set_gate (14, (unsigned int)isr14, 0x08, 0x8E);
  idt_set_gate (15, (unsigned int)isr15, 0x08, 0x8E);

  idt_set_gate (16, (unsigned int)isr16, 0x08, 0x8E);
  idt_set_gate (17, (unsigned int)isr17, 0x08, 0x8E);
  idt_set_gate (18, (unsigned int)isr18, 0x08, 0x8E);
  idt_set_gate (19, (unsigned int)isr19, 0x08, 0x8E);
  idt_set_gate (20, (unsigned int)isr20, 0x08, 0x8E);
  idt_set_gate (21, (unsigned int)isr21, 0x08, 0x8E);
  idt_set_gate (22, (unsigned int)isr22, 0x08, 0x8E);
  idt_set_gate (23, (unsigned int)isr23, 0x08, 0x8E);
  idt_set_gate (24, (unsigned int)isr24, 0x08, 0x8E);
  idt_set_gate (25, (unsigned int)isr25, 0x08, 0x8E);
  idt_set_gate (26, (unsigned int)isr26, 0x08, 0x8E);
  idt_set_gate (27, (unsigned int)isr27, 0x08, 0x8E);
  idt_set_gate (28, (unsigned int)isr28, 0x08, 0x8E);
  idt_set_gate (29, (unsigned int)isr29, 0x08, 0x8E);
  idt_set_gate (30, (unsigned int)isr30, 0x08, 0x8E);
  idt_set_gate (31, (unsigned int)isr31, 0x08, 0x8E);

  printf("Exception handling installed\n");
}

/* This is a simple string array. It contains the message that
*  corresponds to each and every exception. */

static char *exception_messages[] = {
  "Division By Zero",
  "Debug",
  "Non Maskable Interrupt",
  "Breakpoint",
  "Into Detected Overflow",
  "Out of Bounds",
  "Invalid Opcode",
  "No Coprocessor",
  "Double Fault",
  "Coprocessor Segment Overrun",
  "Bad TSS",
  "Segment Not Present",
  "Stack Fault",
  "General Protection Fault",
  "Page Fault",
  "Unknown Interrupt",
  "Coprocessor Fault",
  "Alignment Check",
  "Machine Check",
  "Reserved 01",
  "Reserved 02",
  "Reserved 03",
  "Reserved 04",
  "Reserved 05",
  "Reserved 06",
  "Reserved 07",
  "Reserved 08",
  "Reserved 09",
  "Reserved 10",
  "Reserved 11",
  "Reserved 12",
  "Reserved 13"
};

/* All of our exception handling Interrupt Service Routines will
*  point to this function. This will tell us what exception has
*  happened! Right now, we simply halt the system by hitting an
*  endless loop. All ISRs disable interrupts while they are being
*  serviced as a 'locking' mechanism to prevent an IRQ from
*  happening and messing up kernel data structures */
void fault_handler (struct regs *r)
{
  if (r->int_no < 32)
    {
      dprint ("%s exception.\n", exception_messages[r->int_no]);
      dprint (
	      "eip: 0x%08x   cs:  0x%08x   ss:  0x%08x   uesp: 0x%08x\n",
	      r->eip, r->cs, r->ss, r->useresp);
      dprint (
	      "eax: 0x%08x   ebx: 0x%08x   ecx: 0x%08x   edx:  0x%08x\n",
	      r->eax, r->ebx, r->ecx, r->edx);
      dprint (
	      "edi: 0x%08x   esi: 0x%08x   ebp: 0x%08x   esp:  0x%08x\n",
	      r->edi, r->esi, r->ebp, r->esp);
      dprint (
	      "ds:  0x%08x   es:  0x%08x   fs:  0x%08x   gs:   0x%08x\n",
	      r->ds, r->es, r->fs, r->gs);
      dprint ("eflags: 0x%08x  errcode: 0x%02x  intno: 0x%02x\n",
	      r->eflags, r->err_code, r->int_no);
      dprint ("cr2: %08x\n", _read_cr2());
      if (r->int_no == 14) 
   	handle_page_fault(r);
 

      panic ("exception encountered.");
      for (;;);
    }
}

